﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace VersionManage.Logic
{
    public class AliOSS
    {
        private static AliOSS _alioss;

        private String ossServer;
        private string ossHost;
        private string bucketName = "rpfield-zlerp";

        private AliOSS()
        {
            ossServer = "http://rpfield-zlerp.oss-cn-beijing.aliyuncs.com/dev/devices/";
            ossHost = "http://rpfield-zlerp.oss-cn-beijing.aliyuncs.com/";
            bucketName = "rpfield-zlerp";
        }

        /// <summary>
        /// 创建或获取一个阿里对象存储操作对象
        /// </summary>
        public static AliOSS CreateAliOSS()
        {
            if (_alioss == null)
                _alioss = new AliOSS();
            //FocusServerHttpUtility可能会改变,在使用前重新获取
            //_alioss.foucsHu = HttpUtility.FocusServerHttpUtility;
            //_alioss.ossHU = HttpUtility.CreateUtility(_alioss.CDN, null);
            return _alioss;
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public bool Put(AliObjectStorage info)
        {

            if (OssFileExists(ossServer + info.FileName))
            {
                info.OSSPath = ossServer + info.FileName;
                return true;
            }

            HttpUtility putHttp = new HttpUtility(ossServer, null);
            OssPutRequest opr = new OssPutRequest();
            //opr.OssPath = FileLogic.GetFileMD5(info.Data);
            opr.Data = info.Data;
            putHttp.RequestCreatingEvent += (obj, item) =>
            {
                DateTime utctime = DateTime.UtcNow;
                item.Date = utctime;
                item.Url = putHttp.BaseAddress + info.FileName;
                //Encryption(item,info.OSSPath);
                Encryption(item, item.Url.Replace(ossHost,""));// info.OSSPath);
            };
            HttpResult<String> result = putHttp.GetHttpResult<OssPutRequest, string>(opr);
            info.OSSPath= putHttp.BaseAddress + info.FileName;
            return result.Success;
        }

        /// <summary>
        /// 获取文件属性
        /// </summary>
        /// <param name="ossPath">相对路径</param>
        /// <returns>如果文件不存在返回null</returns>
        public bool OssFileExists(string ossPath)
        {
            HttpResult<string> result= WebLogic.GetHttpResult<string>(new HttpItem { Method = HttpMethod.Head, Url = ossPath });
            if (result.StatusCode == 404)
                return false;
            return true;
        }

        public string GetOssFileUrl(string filePath)
        {
            AliObjectStorage aliObjectStorage = FileLogic.GetFileMD5(filePath);
            if (OssFileExists(ossServer + aliObjectStorage.FileName))
                Put(aliObjectStorage);
            return ossServer + aliObjectStorage.FileName;
        }




        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="ossPath"></param>
        /// <returns></returns>
        public bool Delete(string ossPath)
        {
            HttpUtility deleteHttp = new HttpUtility(CDN + ossPath + "?encoding-type=url", null);
            deleteHttp.RequestCreatingEvent += (obj, item) =>
            {
                item.Date = DateTime.UtcNow;
                Encryption(item, ossPath);
            };

            HttpResult<string> result = deleteHttp.GetHttpResult<OssDelete, string>(new OssDelete());
            if (result.Success)
                return true;
            else if (result.StatusCode == 404)
                return true;
            return false;
        }



        /// <summary>
        /// 获取CDN
        /// </summary>
        /// <returns></returns>
        public string CDN
        {
            get
            {
                return ossServer;
            }

        }

        /// <summary>
        /// 获取签名
        /// </summary>
        /// <returns></returns>
        private string Authorization(string data)
        {
            //本地加密
            //LTAIdhrG7tlfYOUa--- QTeFHiym4l33c5yUu5XWuliMjHmCtX
            //LTAIuQev20xBqmNu---Cr448SaKbcQHebf74znRe5MxFEjzw9
            //return string.Format("OSS {0}:{1}", "LTAIuQev20xBqmNu", ComputeSignatureCore("Cr448SaKbcQHebf74znRe5MxFEjzw9", data));
            return string.Format("OSS {0}:{1}", "LTAIdhrG7tlfYOUa", ComputeSignatureCore("QTeFHiym4l33c5yUu5XWuliMjHmCtX", data));
        }




        /// <summary>
        /// HmacSHA1
        /// </summary>
        /// <param name="key"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private string ComputeSignatureCore(string key, string data)
        {
            using (var algorithm = KeyedHashAlgorithm.Create("HmacSHA1".ToUpperInvariant()))
            {
                algorithm.Key = Encoding.UTF8.GetBytes(key.ToCharArray());
                return Convert.ToBase64String(
                    algorithm.ComputeHash(Encoding.UTF8.GetBytes(data.ToCharArray())));
            }
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="item"></param>
        /// <param name="ossPath"></param>
        private void Encryption(HttpItem item, string ossPath)
        {
            var sb = new StringBuilder();
            sb.Append(item.Method.ToString().ToUpper());
            sb.Append("\n");

            Dictionary<string, string> headers = item.HeadersToDictionary();
            if (headers != null)
                headers = new Dictionary<string, string>();

            var sortedHeaders = new List<string>();
            if (!headers.ContainsKey("Date"))
                headers.Add("Date", item.Date.ToString("R"));
            if (!headers.ContainsKey("Content-Type"))
                headers.Add("Content-Type", item.ContentType.ToString());
            if (!headers.ContainsKey("Content-MD5"))
                headers.Add("Content-MD5", "");

            foreach (var header in headers)
                if (header.Key == "Date" || header.Key == "Content-Type" || header.Key == "Content-MD5" || header.Key.StartsWith("x-oss-"))
                    sortedHeaders.Add(header.Key);
            sortedHeaders.Sort(StringComparer.Ordinal);
            foreach (var key in sortedHeaders)
            {
                if (key.StartsWith("x-oss-"))
                    sb.Append(key).Append(':');
                sb.Append(headers[key] + "\n");
            }

            sb.Append("/"+bucketName+"/" + ossPath);

            for (int i = 0; i < item.Headers.Count; i++)
            {
                if (item.Headers[i].StartsWith("Authorization"))
                {
                    item.Headers[i] = "Authorization: " + Authorization(sb.ToString());
                    return;
                }
            }
            item.Headers.Add("Authorization: " + Authorization(sb.ToString()));
        }
    }

    public enum OssPathMode
    {
        /// <summary>
        /// 文书模版
        /// </summary>
        NotesTemplate = 1,

        /// <summary>
        /// 文件打印记录
        /// </summary>
        NotesRecord = 2,

        /// <summary>
        /// 处方笺模版
        /// </summary>
        PrescriptionTemplate = 3,
        /// <summary>
        /// 医院logo
        /// </summary>
        Logo = 4,

        /// <summary>
        /// 单据凭证
        /// </summary>
        BillCert = 5,

        /// <summary>
        /// 其它
        /// </summary>
        Other=100
    }
}
